﻿using Roton.Memory;
using Roton.ZZT;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Roton.Wrapper
{
    /// <summary>
    /// Adapts IElement to a Segment object.
    /// </summary>
    class ElementWrapper : IElement
    {
        protected ElementWrapperProperties properties;
        private Segment segment;

        public ElementWrapper(int baseOffset, Segment segment, ElementWrapperProperties properties)
        {
            this.segment = segment;
            properties.OffsetAlwaysShown += baseOffset;
            properties.OffsetChar += baseOffset;
            properties.OffsetColor += baseOffset;
            properties.OffsetCycle += baseOffset;
            properties.OffsetDestructible += baseOffset;
            properties.OffsetDrawCodeEnable += baseOffset;
            properties.OffsetEditorBoard += baseOffset;
            properties.OffsetEditorCategory += baseOffset;
            properties.OffsetEditorCode += baseOffset;
            properties.OffsetEditorFloor += baseOffset;
            properties.OffsetEditorP1 += baseOffset;
            properties.OffsetEditorP2 += baseOffset;
            properties.OffsetEditorP3 += baseOffset;
            properties.OffsetEditorStep += baseOffset;
            properties.OffsetFloor += baseOffset;
            properties.OffsetKey += baseOffset;
            properties.OffsetMenu += baseOffset;
            properties.OffsetName += baseOffset;
            properties.OffsetPoints += baseOffset;
            properties.OffsetPushable += baseOffset;
            this.properties = properties;
        }

        public bool AlwaysShown
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetAlwaysShown);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetAlwaysShown, value);
            }
        }

        public int Char
        {
            get
            {
                return segment.Read8(properties.OffsetChar);
            }
            set
            {
                segment.Write8(properties.OffsetChar, value);
            }
        }

        public int Color
        {
            get
            {
                return segment.Read8(properties.OffsetColor);
            }
            set
            {
                segment.Write8(properties.OffsetColor, value);
            }
        }

        public int Cycle
        {
            get
            {
                return segment.Read16(properties.OffsetCycle);
            }
            set
            {
                segment.Write16(properties.OffsetCycle, value);
            }
        }

        public bool Destructible
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetDestructible);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetDestructible, value);
            }
        }

        public bool DrawCodeEnable
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetDrawCodeEnable);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetDrawCodeEnable, value);
            }
        }

        public IString EditorBoard
        {
            get
            {
                return new ByteStringWrapper(properties.OffsetEditorBoard, segment);
            }
        }

        public IString EditorCategory
        {
            get
            {
                return new ByteStringWrapper(properties.OffsetEditorCategory, segment);
            }
        }

        public IString EditorCode
        {
            get
            {
                return new ByteStringWrapper(properties.OffsetEditorCode, segment);
            }
        }

        public bool EditorFloor
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetEditorFloor);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetEditorFloor, value);
            }
        }

        public IString EditorP1
        {
            get
            {
                return new ByteStringWrapper(properties.OffsetEditorP1, segment);
            }
        }

        public IString EditorP2
        {
            get
            {
                return new ByteStringWrapper(properties.OffsetEditorP2, segment);
            }
        }

        public IString EditorP3
        {
            get
            {
                return new ByteStringWrapper(properties.OffsetEditorP3, segment);
            }
        }

        public IString EditorStep
        {
            get
            {
                return new ByteStringWrapper(properties.OffsetEditorStep, segment);
            }
        }

        public bool Floor
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetFloor);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetFloor, value);
            }
        }

        public int Key
        {
            get
            {
                return segment.Read8(properties.OffsetKey);
            }
            set
            {
                segment.Write8(properties.OffsetKey, value);
            }
        }

        public int Menu
        {
            get
            {
                return segment.Read16(properties.OffsetMenu);
            }
            set
            {
                segment.Write16(properties.OffsetMenu, value);
            }
        }

        public IString Name
        {
            get
            {
                return new ByteStringWrapper(properties.OffsetName, segment);
            }
        }

        public int Points
        {
            get
            {
                return segment.Read16(properties.OffsetPoints);
            }
            set
            {
                segment.Write16(properties.OffsetPoints, value);
            }
        }

        public bool Pushable
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetPushable);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetPushable, value);
            }
        }
    }

    struct ElementWrapperProperties
    {
        public int OffsetAlwaysShown;
        public int OffsetChar;
        public int OffsetColor;
        public int OffsetCycle;
        public int OffsetDestructible;
        public int OffsetDrawCodeEnable;
        public int OffsetEditorBoard;
        public int OffsetEditorCategory;
        public int OffsetEditorCode;
        public int OffsetEditorFloor;
        public int OffsetEditorP1;
        public int OffsetEditorP2;
        public int OffsetEditorP3;
        public int OffsetEditorStep;
        public int OffsetFloor;
        public int OffsetKey;
        public int OffsetMenu;
        public int OffsetName;
        public int OffsetPoints;
        public int OffsetPushable;
    }
}
